package model;

import game_engine.GameEngine;
import game_engine.core.Collision;
import game_engine.core.EntityGroup;
import game_engine.core.GameStage;
import game_engine.core.Vector2f;

import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;

import model.entity.Enemy;
import model.entity.Fighter;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;

public class LevelOne implements GameStage {

	private ArrayList<EntityGroup> entities;
	private ArrayList<Collision> collisions;

	public EntityGroup fighter;
	public EntityGroup enemies;

	private boolean start = false;

	private Vector2f leftSpeed = new Vector2f(-1f, 0);
	private Vector2f rightSpeed = new Vector2f(1f, 0);
	private Vector2f topSpeed = new Vector2f(0, -1f);
	private Vector2f bottomSpeed = new Vector2f(0, 1f);

	public LevelOne() {
		loadTexture();
		initialize();
	}

	private void loadTexture() {
		GameEngine ge = GameEngine.getInstance();
		Color transColor = new Color(0xbfdcbf);
		for (int i = 1; i <= 13; i++) {
			if (i < 10)
				ge.addTextureToLoad("images/explo/explo_0" + i + ".png", transColor);
			else
				ge.addTextureToLoad("images/explo/explo_" + i + ".png", transColor);
		}
		ge.addTextureToLoad("images/fighter/fighter_mid.png", transColor);
		ge.addTextureToLoad("images/fighter/fighter_left2.png", transColor);
		ge.addTextureToLoad("images/fighter/fighter_left1.png", transColor);
		ge.addTextureToLoad("images/fighter/fighter_right2.png", transColor);
		ge.addTextureToLoad("images/fighter/fighter_right1.png", transColor);
		ge.addTextureToLoad("images/bullets/fire_bullet1.png", transColor);
		ge.addTextureToLoad("images/bullets/fire_bullet2.png", transColor);
		ge.addTextureToLoad("images/bullets/fire_bullet3.png", transColor);
		ge.addTextureToLoad("images/bullets/fire_bullet4.png", transColor);
		ge.addTextureToLoad("images/enemies/enemy1.png", transColor);

		while (!ge.isAllTextureLoaded()) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
 		}
	}

	private void initialize() {
		entities = new ArrayList<EntityGroup>();
		collisions = new ArrayList<Collision>();

		fighter = new EntityGroup();
		enemies = new EntityGroup();

		entities.add(enemies);
		entities.add(fighter);

		Fighter f = new Fighter(1, "Fighter");
		f.setSpeed(0.2f);
		f.setPosition(new Vector2f(400, 600));
		fighter.addEntity(f);

		entities.add(f.getBullets());

		for (int i = 0; i < 15; i++) {
			for (int j = 0; j < 8; j++) {
				Enemy e = new Enemy("enemy " + (i + j + 1));
				e.setSpeed(0.05f);
				e.setPosition(new Vector2f(i * 50 + 30, j * 50 + 30));
				e.setBox(new Rectangle(0, 0, 30, 30));
				e.setDirection(new Vector2f(0.015f, 0.03f));
				float[] rotations = new float[] { 5f, -5f };
				e.setRotations(rotations);
				int[] rotationsTiming = new int[] { 500, 500 };
				e.setRotationsTiming(rotationsTiming);
				e.setRotationsLoop(true);
				e.setValue(100 + i);
				enemies.addEntity(e);
				entities.add(e.getBullets());
				collisions.add(new Collision(e.getBullets(), fighter, Collision.BOTH));
			}
		}

		collisions.add(new Collision(fighter, enemies, Collision.COL1));
		collisions.add(new Collision(f.getBullets(), enemies, Collision.BOTH));
	}

	@Override
	public void render() {
		for (int i = 0; i < entities.size(); i++) {
			entities.get(i).render();
		}
	}

	@Override
	public void start() {
		this.start = true;
	}

	@Override
	public void stop() {
		start = false;
	}

	@Override
	public boolean isRunning() {
		return start;
	}

	@Override
	public void update(long tick) {
		moveEntities(tick);

		actionEntities(tick);

		checkCollision();

		cleanEntities();

		updateAnimation(tick);

		keyUpdate();
	}

	private void actionEntities(long tick) {
		synchronized (entities) {
			for (int i = 0; i < entities.size(); i++) {
				entities.get(i).doAction(tick);
			}
		}
	}

	private void moveEntities(long tick) {
		for (int i = 0; i < entities.size(); i++) {
			entities.get(i).moveEntities(tick);
		}
	}

	private void updateAnimation(long tick) {
		for (int i = 0; i < entities.size(); i++) {
			entities.get(i).updateAnimation(tick);
		}

	}

	private void cleanEntities() {
		for (int i = 0; i < entities.size(); i++) {
			entities.get(i).cleanEntities();
		}
	}

	private void checkCollision() {
		for (int i = 0; i < collisions.size(); i++) {
			collisions.get(i).checkCollision();
		}
	}

	public void keyUpdate() {
		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
			fighter.getEntities().get(0).addSpeed(leftSpeed);
			fighter.getEntities().get(0).setCurrentAction(Fighter.FRAME_MOVING_LEFT);
		} else
			fighter.getEntities().get(0).removeSpeed(leftSpeed);
		if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
			fighter.getEntities().get(0).setCurrentAction(Fighter.FRAME_MOVING_RIGHT);
			fighter.getEntities().get(0).addSpeed(rightSpeed);
		} else
			fighter.getEntities().get(0).removeSpeed(rightSpeed);
		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT) == Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
			fighter.getEntities().get(0).setCurrentAction(Fighter.FRAME_NOMOVE);
		if (Keyboard.isKeyDown(Keyboard.KEY_UP))
			fighter.getEntities().get(0).addSpeed(topSpeed);
		else
			fighter.getEntities().get(0).removeSpeed(topSpeed);
		if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
			fighter.getEntities().get(0).addSpeed(bottomSpeed);
		else
			fighter.getEntities().get(0).removeSpeed(bottomSpeed);
		if (Keyboard.isKeyDown(Keyboard.KEY_ADD)) {
			fighter.getEntities().get(0).setSpeed(fighter.getEntities().get(0).getSpeed() + 0.1f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_SUBTRACT)) {
			fighter.getEntities().get(0).setSpeed(fighter.getEntities().get(0).getSpeed() - 0.1f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
			Display.destroy();
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_X))
			((Fighter) fighter.getEntities().get(0)).setxShooting(true);
		else
			((Fighter) fighter.getEntities().get(0)).setxShooting(false);
		if (Keyboard.isKeyDown(Keyboard.KEY_W))
			((Fighter) fighter.getEntities().get(0)).setwShooting(true);
		else
			((Fighter) fighter.getEntities().get(0)).setwShooting(false);
	}

}
